import Uid from 'uid-safe';
import Crypto from 'crypto';
import fs from 'fs-extra';
import path from 'path';
import base64 from 'base-64';
const rim = require('rimraf');
import Config from '../conf';
import {getVersion} from '../modules';

const {uploadFiles} = require('../mids');

function filterKeys(data,filter){
	return data.map(res => {
		for(let k in filter){
			delete res[k];
		}
		return res;
	});
}

/**	
 * users
 * [id,name,pswd,admin,auth_types,time]
 */
async function Login(cx,next){
	// let user = await cx.locServe.users.
	let {
		name,
		pswd,
		token,
		bkInfo
	} = cx.request.body;
	/*验证权限*/
	if (token && bkInfo) {
		let vered=await verifyUser.call(cx,token);
		if (vered) {
			cx.body={
				success:false,
				result:vered
			};
			return;
		}
	}
	if (!name || !name.length) {
		cx.body = {
			success:false,
			result:'用户名不能为空！'
		}
		return;
	}
	if (!pswd || !pswd.length) {
		cx.body = {
			success: false,
			result: '密码不能为空！'
		}
		return;
	}

	let users = await cx.locServe.users.find();
	let userInfo = users.filter(u => u.name === name);
	
	if (userInfo.length) {
		if(userInfo[0].pswd !== cryptoPswd(pswd)){
			cx.body = {
				success: false,
				result: '密码不正确！'
			}
			return;
		}else{
			let token = await cx.jwt.sign(bkInfo? {bkInfo}: {userInfo: userInfo[0]});
			cx.body = {
				success: true,
				result: token,
				userInfo: bkInfo? 0: userInfo[0]
			};
		};
	}else{
		cx.body = {
			success: false,
			result: '该用户不存在！'
		}
		return;
	}
	
}
/*
 * 权限判断
*/
async function verifyUser(token,could){
	if (!token) return 'token丢失，请重新登录！'

	let uInfo = this.jwt.verify(token);
	if (uInfo==='jwt expired') return 'token过期，请重新登录！';
	if (uInfo==='jwt malformed') return 'token无效，请重新登录！';
	// jwt expired 
	// jwt malformed
	console.log(uInfo)   

	if (!could&&Object.keys(uInfo.userInfo).length&&uInfo.userInfo.admin!=='1') return '无权限操作！';
}

function cryptoPswd(pswd){
	let hash = Crypto.createHash("md5");
	hash.update(pswd);
	return hash.digest('hex');
}
async function addUser(cx,next){

	let id = Uid.sync(20);
	let {
		name,
		pswd,
		admin,
		token
	} = cx.request.body;
	if (name===undefined||pswd===undefined) {
		cx.body={
			success:false,
			result:'用户信息不全！'
		};
		return;
	}
	
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	/*
	 * 筛选name
	*/
	let users = await cx.locServe.users.find();
	let userInfo = users.filter(u=>u.name===name);
	if (userInfo.length) {
		cx.body = {
			success:false,
			result:'该用户已存在！'
		}
		return;
	}
	if (!name.length) {
		cx.body = {
			success:false,
			result:'用户名不能为空！'
		}
		return;
	}
	if (!pswd.length) {
		cx.body = {
			success:false,
			result:'密码不能为空！'
		}
		return;
	}

	await cx.locServe.users.insert({
		id,
		name,
		pswd:cryptoPswd(pswd),
		admin:admin||"0",
		time:new Date().toLocaleString()
	});
	cx.body = {
		success:true,
		result:'已成功新增用户！'
	}
}
async function removeUser(cx,next){
	
	let {id,token} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}

	await cx.locServe.users.remove({id});
	cx.body={
		success:true,
		result:'用户删除成功！'
	};
}
async function updateUser(cx,next){
	let {id,name,pswd,token} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	await cx.locServe.users.update({id},{name,pswd:cryptoPswd(pswd)});
	cx.body={
		success:true,
		result:'用户修改成功！'
	};
}
async function usersList(cx,next){
	let {token} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	let result = await cx.locServe.users.find({},{pswd:0,time:0});
	for(let i=0; i<result.length; i++){
		let userId = result[i].id;
		let userBooks = await cx.locServe.books.find({userId});
		let books = userBooks.length;
		let mdBooks = await cx.locServe.books.find({isMdpage: '1'});
		mdBooks.forEach(md => {
			if (md.books && md.books.length) {
				md.books.forEach(bk => {
					if (bk.userId === userId) books++;
				});
			}
		}); 
		result[i].books = books;
	}
	cx.body={
		success:true,
		result
	}
}
async function booksList(cx,next){
	let {userId,token} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token,1);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	let result = [];
	let isAdmin = 0;
	let user = await cx.locServe.users.find({id:userId});
	if (user.length) {
		isAdmin = user[0].admin;
		let query = {};
		if (isAdmin==0) {
			query = {userId};
		}
		result = await cx.locServe.books.find(query);
	}
	
	cx.body={
		success:true,
		result,
		isAdmin
	}
}

async function addType(cx,next){
	let {token,name} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}

	let id = Uid.sync(20);
	await cx.locServe.types.insert({
		id,
		name
	});
	cx.body = {
		success:true,
		result:id
	}
}
async function typesList(cx,next){
	let types = await cx.locServe.types.find();
	cx.body = {
		success:true,
		result:types
	}
}
async function updateType(cx,next){
	let {token,id,name} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	let books = await cx.locServe.books.find({typesId:new RegExp(id,'gi')});
	if (books.length) {
		cx.body={
			success:false,
			result:'该分类里已有数据！'
		}
		return;
	}
	await cx.locServe.types.update({id},{name});
	cx.body = {
		success:true,
		result:'ok'
	}
}
async function removeType(cx,next){
	let {token,id} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	// 有books数据的不可删
	let books = await cx.locServe.books.find();
	let has = 0;
	books.forEach(bk=>{
		if (~bk.typesId.indexOf(id)) has++;
	});
	if (has) {
		cx.body = {
			success:false,
			result:'该分类里已有数据！'
		}
		return;
	}
	await cx.locServe.types.remove({id});
	cx.body = {
		success:true,
		result:'ok'
	}
}
async function repswd(cx,next){
	let {token,id,pswd1,pswd2} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token,1);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	if (!id||!pswd1||!pswd2) {
		cx.body={
			success:false,
			result:'params id,pswd1,pswd2 excepted'
		}
		return;
	}
	let user = await cx.locServe.users.find({id,pswd:cryptoPswd(pswd1)});
	if (!user.length) {
		cx.body={
			success:false,
			result:'原密码不正确！'
		}
		return;
	}
	await cx.locServe.users.update({id},{pswd:cryptoPswd(pswd2)});
	cx.body={
		success:true,
		result:'ok'
	}
}

async function addBook(cx,next){
	// {
	// 	dirname:'',
	// 	books:[
	// 		{},
	// 		{}
	// 	]
	// }
	let {parentId,id,token,tempid,dirname,name,desc,author,userId,typesId,typesName,logo,index,bookjson,bookDir,isMdpage,version} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token,1);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	let dirname_book = await cx.locServe.books.find({dirname}); 
	if (dirname_book.length && !id && !parentId) {
		cx.body={
			success:false,
			result:'路径已存在！'
		};
		return;
	}
	if (!id) {
		// 新增
		let _book = await cx.locServe.books.find({name});
		if (_book.length) {
			cx.body={
				success:false,
				result:'书名重复！'
			}
			return;
		}
	}
	let book = {
		name,
		desc,
		author,
		userId,
		typesId,
		typesName,
		logo,
		dirname,
		// index,
		bookjson,
		bookDir,
		isMdpage,
		version,
		id:id||Uid.sync(20),
		time:new Date().toLocaleString()
	}
	let uploaded = path.join(process.cwd(), Config.upload.uploadedDir);
	let _dirname = path.join(uploaded, dirname);
	
	let resBook = [];
	if (id) { // 修改
		
		if (isMdpage == '1') { // markdown
			let mdbook=await cx.locServe.books.find({parentId, isMdpage});
			if (mdbook.length) {
				mdbook=mdbook[0];
				if (mdbook.dirname!==dirname) {
					fs.renameSync(path.join(uploaded, mdbook.dirname), _dirname);
				}
				mdbook.dirname=dirname;
				mdbook.index=index;
				if (!~mdbook.versions.indexOf(version)) { // 新版
					mdbook.versions.push(version);
					mdbook.books.push(Object.assign(book,{id:Uid.sync(20), pv: 0}));
				}else{
					mdbook.books.forEach(mk=>{
						if (mk.id===id) {
							for(let k in mk){
								mk[k]=book[k];
							}
						}
					});
				}
			}
			resBook = mdbook;
			await cx.locServe.books.update({parentId, isMdpage}, mdbook);
		}else{
			resBook = book;
			let abook = await cx.locServe.books.find({id});
			if (abook.length) abook = abook[0];
			book.index=index;
			await cx.locServe.books.update({id}, book);
			if (abook.dirname!==dirname) {
				fs.renameSync(path.join(uploaded, abook.dirname), _dirname);
			}
		}
	}else{
		let oldbook=Object.assign(book, {pv: 0, index});
		let newbook = isMdpage == '1'? {
			parentId:Uid.sync(20),
			dirname,
			isMdpage,
			index,
			versions:[version],
			books:[oldbook]
		}: oldbook;
		resBook = newbook;
		await cx.locServe.books.insert(newbook);
	}
	let tempBookDir = path.join(process.cwd(),Config.upload.uploadedDir,'/'+tempid);
	let hasTempDirname = fs.existsSync(tempBookDir);
	if (hasTempDirname) {
		let hasDirname = fs.existsSync(_dirname);
		if(!hasDirname) fs.mkdirSync(_dirname);

		// hasSummary区分旧版纯html页面和新版纯markdown
		let hasSummary = fs.existsSync(path.join(tempBookDir,bookDir,'SUMMARY.md'));
		if (hasSummary) {
			let versionDir = versionCtrl(bookjson, _dirname);
			if (versionDir) _dirname = versionDir;
		}
		fs.copySync(path.join(tempBookDir,bookDir),_dirname);
		try{
			process.nextTick(() => {
				fs.remove(tempBookDir);
			});
		}catch(e){console.log(e)}
	}
	cx.body={
		success:true,
		result:resBook
	}
}
function versionCtrl(bookjson, _dirname) {
	try{
		bookjson = JSON.parse(decodeURIComponent(base64.decode(bookjson)));
	}catch(e){
		bookjson = 0;
	}
	
	if (bookjson) {
		let verionDir = path.join(_dirname, bookjson.version || '1.0.0'); 
		let hasVersion = fs.existsSync(verionDir);
		if (!hasVersion) {
			fs.mkdirSync(verionDir);
		}
		return verionDir;
	}
	
}
async function removeBook(cx,next){
	let {token,parentId,id,userId,_name,version} = cx.request.body;
	/*验证权限*/
	let vered=await verifyUser.call(cx,token,1);
	
	if (vered) {
		cx.body={
			success:false,
			result:vered
		};
		return;
	}
	if (!id||!userId) {
		cx.body={
			success:false,
			result:'params id,userId excepted !'
		};
		return;
	}
	let removeBookFiles=function(delall){
		if (_name) {
			var delPath=path.join(process.cwd(),Config.upload.uploadedDir,path.join(_name,parentId&&!delall?version:''));
			try{
				process.nextTick(() => {
					rim.sync(delPath);
				});
			}catch(e){}
		}
	}
	let _user = await cx.locServe.users.find({id:userId});
	if (_user.length&&_user[0].admin==1) {
		if (parentId) {
			let _bk = await filterMdbook(bk => bk.id !== id);
			if (_bk) {
				await cx.locServe.books.update({parentId}, _bk);
				removeBookFiles(0);
			}else{
				await cx.locServe.books.remove({parentId});
				removeBookFiles(1);
			}
			
		}else{
			await cx.locServe.books.remove({id});
			removeBookFiles(1);
		}
	}else{
		if (parentId) {
			let _bk = await filterMdbook(bk => bk.id !== id && bk.userId != userId);
			if (_bk) {
				await cx.locServe.books.update({parentId}, _bk);
				removeBookFiles(0);
			}else{
				await cx.locServe.books.remove({parentId});
				removeBookFiles(1);
			}
			
		}else{
			await cx.locServe.books.remove({id,userId});
			removeBookFiles(1);
		}
	}
	async function filterMdbook(filter){
		let mdbook = await cx.locServe.books.find({parentId});
		if (mdbook.length) {
			mdbook = mdbook[0];
			mdbook.versions = mdbook.versions.filter(v => v !== version);
			if(mdbook.books) mdbook.books = mdbook.books.filter(filter);
		}
		return mdbook.books.length?mdbook:0;
	}
	cx.body={
		success:true,
		result:'已删除！'
	};
}
let filter = {bookjson:0,bookDir:0,time:0,typesId:0,userId:0};
async function search(cx,next){
	let { key, value } = cx.request.body; // typesName,name
	let filterBooks =  async function(type, v){
		let res = [], all = [];
		if (type) {
			let keyReg = new RegExp(v,'gi');
			let books = await cx.locServe.books.find();
			books.forEach(bk => {
				if (bk[type]) {
					keyReg.lastIndex = 0;
					if (keyReg.test(bk[type])) {
						res.push(bk);
					}else{
						all.push(bk);
					}
				}
				if (bk.books && bk.books.length) {
					bk.books.forEach(book => {
						if (book[type]) { // lastIndex
							keyReg.lastIndex = 0;
							if (keyReg.test(book[type])) {
								res.push({...book, parentId: bk.parentId});
							}else{
								all.push(book);
							}
						}
					});
				}
			});
		}
		return !v || v === '全部'? all: res;
	}
	cx.body={
		success:true,
		result:filterKeys(await filterBooks(key, value), filter)
	}
}

async function beforePageBooks(cx,next){
	let result = await cx.locServe.books.find({},filter);
	let resBooks = [];
	result.forEach(res => {
		if (res.isMdpage === '1') {
			if (res.books && res.books.length) {
				res.books.forEach(bk => {
					resBooks.push({...bk, index: res.index, parentId: res.parentId});
				});
			}
		}else{
			resBooks.push(res);
		}
	});
	
	cx.body={
		success:true,
		result:filterKeys(resBooks,filter)
	}
}
async function increasePv(cx,next){
	let { parentId, id } = cx.request.body;
	let pv = 0;
	let query = parentId? {parentId}: {id};
	let book = await cx.locServe.books.find(query);
	if (book.length) book = book[0];
	if (parentId) {
		if (book && book.books && book.books.length) {
			for(let i=0;i<book.books.length;i++){
				let bk = book.books[i];
				if (bk.id === id) {
					pv = ~~bk.pv+1;
					bk.pv = pv;
					break;
				}
			}
			await cx.locServe.books.update({parentId},{books: book.books}); 
		}
	}else{
		pv = ~~book.pv+1;
		await cx.locServe.books.update({id}, {pv});
	}
	
	cx.body={
		success:true,
		result:pv
	}
	
}
async function isExistsDirname(cx,next){
	let { dirname,id } = cx.request.body;
	let book = await cx.locServe.books.find({dirname}); 
	if (book.length&&book[0].id!==id) {
		cx.body={
			success:true,
			result:'路径已存在！'
		}
		return;
	}
	cx.body={
		success:false,
		result:'ok'
	}
}

const APIs = {
	'/api/user/login':Login,
	'/api/user/addUser':addUser,
	'/api/user/removeUser':removeUser,
	'/api/user/updateUser':updateUser,
	'/api/user/usersList':usersList,
	'/api/user/repswd':repswd,
	'/api/book/booksList':booksList,
	'/api/book/addBook':addBook,
	'/api/type/typesList':typesList,
	'/api/type/addType':addType,
	'/api/type/updateType':updateType,
	'/api/type/removeType':removeType,
	'/api/book/upload':uploadFiles,
	'/api/book/removeBook':removeBook,
	'/api/book/search':search,
	'/api/book/beforePageBooks':beforePageBooks,
	'/api/book/increasePv':increasePv,
	'/api/book/isExistsDirname':isExistsDirname,
	// just a default route type
	__setDefaultType__:'post'
}

export default APIs;
